package com.github.core.parse.spel;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.system.SystemUtil;
import cn.hutool.system.UserInfo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.*;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @author 陈敏
 * @version ExpressionConfiguration.java, v 1.1 2021/4/27 10:29 chenmin Exp $
 * Created on 2021/4/27
 * 
 */
@Configuration
public class SpelConfiguration implements ApplicationContextAware {

    @Getter
    @Setter
    private ApplicationContext applicationContext;

    @Bean
    @ConditionalOnMissingBean
    public SpelParserConfiguration spelParserConfiguration() {
        return new SpelParserConfiguration();
    }

    @Bean
    @ConditionalOnMissingBean
    public ExpressionParser expressionParser(SpelParserConfiguration spelParserConfiguration) {
        return new SpelExpressionParser(spelParserConfiguration);
    }

    @Bean
    @ConditionalOnMissingBean
    public EvaluationContext evaluationContext(BeanResolver beanResolver, List<PropertyAccessor> propertyAccessors) {
        //创建一个虚拟的容器EvaluationContext
        StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
        propertyAccessors.forEach(evaluationContext::addPropertyAccessor);
        evaluationContext.setBeanResolver(beanResolver);

        evaluationContext.setRootObject(getRootObject());
        // 注册自定义函数
        Method[] methods = ReflectUtil.getPublicMethods(SpelFunction.class);
        if (ObjectUtil.isNotEmpty(methods)) {
            for (Method method : methods) {
                evaluationContext.registerFunction(method.getName(), method);
            }
        }
        return evaluationContext;
    }

    @Bean
    @ConditionalOnMissingBean
    public ParserContext templateParserContext() {
        return ParserContext.TEMPLATE_EXPRESSION;
    }

    @Bean
    @ConditionalOnMissingBean
    public BeanResolver beanResolver() {
        return new BeanFactoryResolver(applicationContext);
    }

    @Bean
    public PropertyAccessor propertyAccessor() {
        return new SpelJsonPropertyAccessor();
    }

    @Bean
    public SpelParser spelParser(ExpressionParser expressionParser, EvaluationContext evaluationContext, ParserContext parserContext) {
        return new SpelParser()
                .setExpressionParser(expressionParser)
                .setEvaluationContext(evaluationContext)
                .setParserContext(parserContext);
    }

    private JSONObject getRootObject() {
        UserInfo userInfo = SystemUtil.getUserInfo();
        JSONObject rootObject = new JSONObject();
        rootObject.set("SYSTEM_USER_NAME", userInfo.getName());
        rootObject.set("SYSTEM_USER_HOME", userInfo.getHomeDir());
        rootObject.set("SYSTEM_USER_DIR", userInfo.getCurrentDir());
        rootObject.set("SYSTEM_JAVA_IO_TMPDIR", userInfo.getTempDir());
        rootObject.set("SYSTEM_USER_LANGUAGE", userInfo.getLanguage());
        rootObject.set("SYSTEM_USER_COUNTRY", userInfo.getCountry());
        return rootObject;
    }

}
